<template>
  <el-select
    v-model="selectedValue"
    :disabled="disabled"
    :clearable="clearable"
    :filterable="filterable"
    :placeholder="placeholder"
    @change="handleChange"
    class="async-select"
  >
    <el-option
      v-for="option in dropdownOptions"
      :key="option.value"
      :label="option.label"
      :value="option.value"
    />
  </el-select>
</template>

<script>
/**
 *
 *      类型 async-select 异步下拉框(支持字段间依赖) 用法：
 *
 *      import { list as buildingListRaw } from "@/api/elevator-archives/configuration/building.js";
 *      import { list as estateListRaw } from "@/api/elevator-archives/configuration/housingMgt.js";
 *
 *      this.formData = {
 *        estateId: { label: '安装小区', required: true, value: '', width:'50%', rightGap: '10px', type:'async-select', api:estateListRaw },
 *        buildingId: { label: '安装楼栋', required: true, value: '', width: '50%', leftGap: '10px', type:'async-select', api:buildingListRaw, dependencies:['estateId']}, // dependencies 数组接收依赖的其他字段名
 *      ...}
 *
 *      同时需要为使用 async-select 的字段增加change事件
 *      methods: {
 *        change(data) {
 *          ...
 *          this.asyncSelectListener(this.formData, data);
 *          ...
 *        }
 *        以上使用detail_mixin 方法：this.asyncSelectListener(this.formData, data)
 *
 *        或者：
 *        change(data) {
 *          if (data && data.prop === 'estateId') {
 *            this.$set(this.formData.estateId, 'value', data.value);
 *          }
 *
 *          if (data && data.prop === 'buildingId') {
 *            this.$set(this.formData.buildingId, 'value', data.value);
 *          }
 *        }
 *
 *      使用参考 src\views\elevator-archives\configuration\equipments\components\ItemDetail.vue
 *
 */
export default {
  name: "AsyncSelect",
  props: {
    hasDefaultValue: {
      type: Boolean,
      default: false,
    },
    editMode:{
      type: String,
      default: 'detail',
    },
    fieldName:{
      type: String,
      default: '',
    },
    value: {
      type: [String, Number],
      default: '',
    },
    api: {
      type: Function,
      default: null,
    },
    apiParams: {
      type: Object,
      default: () => ({
        pageSize: 999,
        pageNum: 1
      }),
    },
    optionMapping:{
      type: Object,
      default: () => ({
        value: '',
        label: ''
      }),
    },
    formData: {
      type: Object,
      default: () => {},
    },
    dependencies: {
      type: Array,
      default: () => [],
    },
    defaultDropdownOptions: {
      type: Array,
      default: () => [],
    },
    disabled: {
      type: Boolean,
      default: false,
    },
    clearable: {
      type: Boolean,
      default: false,
    },
    filterable: {
      type: Boolean,
      default: false,
    },
    placeholder: {
      type: String,
      default: "请选择",
    },
  },
  data() {
    return {
      selectedValue: this.value,
      dropdownOptions: this.defaultDropdownOptions,
      lastDependencyValues: [],
      queryForm: {},
      inEdit: false,
    };
  },
  computed: {
    newFormData() {
      return JSON.parse(JSON.stringify(this.formData));
    }
  },
  watch: {
    editMode: {
      async handler(val) {
        if (this.hasDefaultValue) {
          this.selectedValue = this.value;
        } else {
          this.selectedValue = '';
        }

        this.setOptions();
      },
      immediate: true,
    },
    defaultDropdownOptions: {
      handler(val) {
        console.log('defaultDropdownOptions:', val);
        this.setOptions();
      },
    },
    newFormData: {
      handler(newForm, oldForm) {
        if (this.editMode==='detail') {
            this.selectedValue = newForm[this.fieldName].value;
            this.dropdownOptions = [];
            this.setOptions();
        } else {
          // console.log('now filed:', this.fieldName)
          if (this.dependenciesChange(newForm, oldForm, this.dependencies)) {
            // 编辑状态初始化时，为各个状态赋初始值
            if (this.dependencies && this.dependencies.length && typeof(this.dependencies[0])=== 'string') {
              if (this.dependencies.some(item => oldForm[item].value==='') && this.dependencies.some(item => newForm[item].value!=='')) {
                this.selectedValue = newForm[this.fieldName].value;
              } else {
                // 在修改过程中，依赖的值如果变化，则自身选项清空，重新根据新的依赖值拉取下拉数据
                this.selectedValue = '';
                this.dropdownOptions = [];
                this.handleChange('');
              }

              this.setOptions();
            } else if (this.dependencies && this.dependencies.length && typeof(this.dependencies[0])=== 'object') {
              if (this.dependencies.some(item => oldForm[item.dependField].value==='') && this.dependencies.some(item => newForm[item.dependField].value!=='')) {
                this.selectedValue = newForm[this.fieldName].value;
              } else {
                // 在修改过程中，依赖的值如果变化，则自身选项清空，重新根据新的依赖值拉取下拉数据
                this.selectedValue = '';
                this.dropdownOptions = [];
                this.handleChange('');
              }

              this.setOptions();
            }
          } else {
            this.selectedValue = newForm[this.fieldName].value;
            this.dropdownOptions = [];
            this.setOptions();
          }
        }
      },
      deep: true,
    }
  },
  created() {
  },
  mounted() {
  },
  methods: {
    handleModelValue(data, value){
      let result = data.find(item => {
        return item.value == value
      })
      return result?result.value:''
    },
    handleChange(newVal) {
      this.$emit("change", newVal);
      console.log('newVA:', newVal)
    },
    dependenciesChange(newForm, oldForm, dependencies) {
      let changed = false;

      if (typeof(dependencies[0]) === 'string') {
        for (let i=0; i<dependencies.length; i++) {
          if (newForm[dependencies[i]].value !== oldForm[dependencies[i]].value) {
            changed = true;
            break;
          }
        }
      } else {
        for (let i=0; i<dependencies.length; i++) {
          if (newForm[dependencies[i].dependField].value !== oldForm[dependencies[i].dependField].value) {
            changed = true;
            break;
          }
        }
      }

      return changed;
    },
    async setOptions() {
      if (this.dropdownOptions && this.dropdownOptions.length > 0) {
        return;
      }

      if (this.api) {
        try {
          let res = [];
          let generatedForm = this.generateDependenciesForm(this.dependencies);
          let emptyValues = Object.values(generatedForm).filter(item => item === '');

          if (emptyValues && emptyValues.length) {
            // 有空值，不走接口调用下拉数据
            // console.log(`${this.fieldName} has emptyValues`);
          } else {
            // console.log(`${this.fieldName} fetching options`);
            res = await this.api(Object.assign({}, this.generateApiParams(this.apiParams), this.generateDependenciesForm(this.dependencies)));
          }

          if (res && res.rows && res.rows.length>=0) {
            this.dropdownOptions = res.rows.map(item => {
              return {
                value: item[this.optionMapping.value ? this.optionMapping.value : (this.guessPropFieldName(item) + 'Id')],
                label: item[this.optionMapping.label ? this.optionMapping.label : (this.guessPropFieldName(item) + 'Name')]
              }
            });
          } else {
            this.dropdownOptions = [];
          }
          // 下拉框匹配不到值赋空
          this.selectedValue = this.handleModelValue(this.dropdownOptions, this.selectedValue);
        } catch (error) {
          console.error("Error fetching options:", error);
        }
      }
    },
    countUpperCase(str) {
      let count = 0;

      for (let i = 0; i < str.length; i++) {
        if (str[i] >= 'A' && str[i] <= 'Z') {
          count++;
        }
      }

      return count;
    },
    generateApiParams(params) {
      if (params && (!params.pageSize)) {
        params['pageSize']= 999;
      }

      if (params && (!params.pageNum)) {
        params['pageNum']= 1;
      }

      return params;
    },
    findKeyInRowKeys(row) {
      let arr = Object.keys(row);

      let wills = [];

      for (let i=0; i<arr.length; i++) {
        let field = arr[i];

        if (field.endsWith('Id')) {
          if (wills.includes(field.slice(0, -2))) {
            break;
          } else {
            wills.push(field.slice(0, -2));
          }
        }

        if (field.endsWith('Name')) {
          if (wills.includes(field.slice(0, -4))) {
            break;
          } else {
            wills.push(field.slice(0, -4));
          }
        }
      }

      if (wills.length) {
        return wills[0];
      } else {
        return '';
      }
    },
    guessPropFieldName(rowData) {
      let name = this.fieldName;

      if (this.findKeyInRowKeys(rowData)!== '') {
        return this.findKeyInRowKeys(rowData);
      } else if (name.endsWith('Id') && this.countUpperCase(this.fieldName) === 1) {
        return name.replace('Id', '');
      } else if (name.endsWith('Name') && this.countUpperCase(this.fieldName) === 1) {
        return name.replace('Name', '');
      } else {
        return rowData[0];
      }
    },
    generateDependenciesForm(dependencies) {
      this.queryForm = {};

      // console.log('this field:', this.fieldName);

      if (dependencies.length) {
        if (typeof(dependencies[0])==='string') {
          // 传的dependencies数组是字段名组成的字符串数组，类似 ['estateId', 'buildingId']
          dependencies.forEach(idName => {
            this.queryForm[idName] = this.newFormData[idName].value;
          });
        } else {
          // 传的是对象数组
          dependencies.forEach(item => {
            this.queryForm[item.mappingField] = this.newFormData[item.dependField].value;
          });
        }
      }

      return this.queryForm;
    },
  },
};
</script>
<style lang="scss" scoped>
.el-theme1 .el-select.async-select {
  width: 100%;
}
</style>
